<?php


namespace UU\Suite\Kernel;


use GuzzleHttp\Client;
use Psr\Http\Message\ResponseInterface;
use UU\Suite\Kernel\Contracts\AccessTokenAwareHttpClientInterface;
use UU\Suite\Kernel\Contracts\AccessTokenInterface;
use UU\Suite\Kernel\Contracts\HttpClientInterface;

/**
 * @method  patch(string|array $uri = [], array $options = [])
 * @method  put(string|array $uri = [], array $options = [])
 * @method  delete(string|array $uri = [], array $options = [])
 */
class HttpClient implements AccessTokenAwareHttpClientInterface, HttpClientInterface
{
    /**
     * @var AccessTokenInterface|null
     */
    protected $accessToken;

    /**
     * @var Client|null
     */
    protected $client = null;


    public function withAccessToken(AccessTokenInterface $accessToken): self
    {
        $clone = clone $this;

        $clone->accessToken = $accessToken;

        return $clone;
    }

    public function __construct(
        $client = null,
        string $uri = '/',
        ?AccessTokenInterface $accessToken = null
    )
    {
        $this->uri = $uri;
        $this->client = $client ?? new Client();
        $this->accessToken = $accessToken;
    }

    /**
     */
    public function requestJson(string $method, string $url, array $options = []): array
    {
        return $this->toArray($this->client->request($method, ltrim($url, '/'), $options));
    }

    /**
     */
    public function request(string $method, string $url, array $options = []): array
    {
        if ($this->accessToken) {
            $options['query'] = \array_merge($options['query'] ?? [], $this->accessToken->toQuery());
        }
        return $this->toArray($this->client->request($method, ltrim($url, '/'), $options));
    }

    /**
     */
    public function get(string $url, array $options = []): array
    {
        if ($this->accessToken) {
            $options['query'] = \array_merge($options['query'] ?? [], $this->accessToken->toQuery());
        }
        return $this->toArray($this->client->request('GET', ltrim($url, '/'), $options));
    }

    /**
     */
    public function post(string $url, array $options = []): array
    {
        if ($this->accessToken) {
            $options['query'] = \array_merge($options['query'] ?? [], $this->accessToken->toQuery());
        }

        return $this->toArray($this->client->request('POST', ltrim($url, '/'), $options));
    }

    public function toArray(ResponseInterface $response)
    {
        return json_decode($response->getBody()->getContents(), JSON_UNESCAPED_UNICODE);
    }

}